package com.jingtuo.java.practice;

import java.util.Arrays;
import java.util.Comparator;

/**
 * 踩过的坑:
 * 1. 题目理解错误, 是寻找机器人经过的所有点中距离原点最远的距离平方, 第一次做完给出的是最终停在的那个点的距离平方
 * 2. 耗时太长, 每次都遍历所有的障碍物。耗时1501ms,击败5.07%的Java提交用户; 内存消耗:43.5MB,击败92.8%的Java提交用户
 * 3. 尝试基于Map缓存x坐标和y坐标对应的点,减少对所有障碍物的遍历。耗时69ms,击败7.79%的Java提交用户;内存消耗:48.1MB,击败5.06%的Java提交用户\
 * 4. 基于二分法找到优化算法。耗时253ms,击败5.87%的Java提交用户; 内存消耗:44.8MB,击败19.94%的Java提交用户
 * 5. 当障碍物出现{0, 0}, 应该能行走, 否则在力扣网站提交会执行失败
 * 6. 不是每次移动都需要遍历所有障碍物, 在方向未发生变化的时候, 仅在当前所在的横轴或者竖轴上找障碍物, 耗时45ms,击败35.97%的Java提交用户; 内存消耗:43.6MB,击败85.92%的Java提交用户
 * 7. 在力扣网站提交代码时, 建议移除不必要的日志, 否则会影响耗时
 * 8. 力扣网站评测数据波动有时候比较大
 * 以上解析思路是正向思维, 寻找答案; 想提高耗时和内存消耗, 需要基于逆向思维, 从答案反推。
 * @author JingTuo
 */
public class SimulateRobotWalk {

    /*
     * 命令数量的最小值
     */
    private static final int COMMAND_MIN_COUNT = 1;

    /*
     * 命令数量的最大值
     */
    private static final int COMMAND_MAX_COUNT = (int) Math.pow(10, 4);

    /*
     * 命令有效值
     */
    private static final int[] COMMANDS = {-2, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9};

    /**
     * 朝北
     */
    private static final int DIRECTION_NORTH = 0;

    /**
     * 朝东
     */
    private static final int DIRECTION_EAST = 1;

    /**
     * 朝南
     */
    private static final int DIRECTION_SOUTH = 2;

    /**
     * 朝西
     */
    private static final int DIRECTION_WEST = 3;

    private static final int LEFT = -2;

    private static final int RIGHT = -1;

    private static final int DISTANCE_MAX = (int) Math.pow(2, 31);

    public static int robotSim(int[] commands, int[][] obstacles) {
        int cLength = commands == null ? 0 : commands.length;
        //参数校验
        if (cLength <= 0 || cLength > COMMAND_MAX_COUNT) {
            System.err.println(COMMAND_MIN_COUNT + " <= commands.length <= " + COMMAND_MAX_COUNT);
            return 0;
        }
        int oLength = obstacles == null ? 0 : obstacles.length;
        if (oLength > COMMAND_MAX_COUNT) {
            System.err.println("0 <= obstacles.length <= " + COMMAND_MAX_COUNT);
            return 0;
        }
        //起点
        int startX = 0;
        int startY = 0;
        //默认朝北
        int curDirection = DIRECTION_NORTH;
        int moveDistance = 0;
        int moveDistanceMax = 0;
        int[][] obstaclesOrderByX = null;
        int[][] obstaclesOrderByY = null;
        if (obstacles != null) {
            //按照x坐标进行排序
            Arrays.sort(obstacles, new Comparator<int[]>() {
                @Override
                public int compare(int[] intLeft, int[] intRight) {
                    if (intLeft[0] < intRight[0]) {
                        return -1;
                    }
                    if (intLeft[0] > intRight[0]) {
                        return 1;
                    }
                    if (intLeft[1] < intRight[1]) {
                        return -1;
                    }
                    if (intLeft[1] > intRight[1]) {
                        return 1;
                    }
                    return 0;
                }
            });
            obstaclesOrderByX = Arrays.copyOf(obstacles, oLength);
            //按照y坐标进行排序
            Arrays.sort(obstacles, new Comparator<int[]>() {
                @Override
                public int compare(int[] intLeft, int[] intRight) {
                    if (intLeft[1] < intRight[1]) {
                        return -1;
                    }
                    if (intLeft[1] > intRight[1]) {
                        return 1;
                    }
                    if (intLeft[0] < intRight[0]) {
                        return -1;
                    }
                    if (intLeft[0] > intRight[0]) {
                        return 1;
                    }
                    return 0;
                }
            });
            obstaclesOrderByY = Arrays.copyOf(obstacles, oLength);
        }


        int previousDirection = -1;
        int previousCommand;
        //当前朝向及其反向的障碍物
        int[][] curObstacleOnAxis = null;
        for (int i = 0; i < cLength; i++) {
            if (checkCommandValid(commands[i])) {
                if (commands[i] < 0) {
                    //方向指令
                    int previousIndex = i - 1;
                    //如果第一个指令是方向指令, previousDirection是当前的朝向
                    if (previousIndex >= 0) {
                        previousCommand = commands[previousIndex];
                        if (previousCommand > 0) {
                            //前一个是移动指令, 当前指令是方向指令, 记录转向之前的朝向
                            previousDirection = curDirection;
                        }
                    }
                    curDirection = getNextDirection(curDirection, commands[i]);
                } else {
                    //移动指令
                    //朝东走, y不变, x变
                    boolean moveOnXAxis = DIRECTION_EAST == curDirection || DIRECTION_WEST == curDirection;
                    int distance = commands[i];
                    if (DIRECTION_SOUTH == curDirection || DIRECTION_WEST == curDirection) {
                        //朝南走和朝西走,是向后走
                        distance = -distance;
                    }
                    if (previousDirection != curDirection) {
                        //朝向发生变化, 找到当前朝向的最近障碍物
                        previousDirection = curDirection;
                        if (moveOnXAxis) {
                            //x轴上移动
                            curObstacleOnAxis = findObstaclesOnXAxis(startX, startY, obstaclesOrderByY);
                        } else {
                            //y轴上移动
                            curObstacleOnAxis = findObstaclesOnYAxis(startX, startY, obstaclesOrderByX);
                        }
                    }
                    if (moveOnXAxis) {
                        //x轴上移动
                        if (curObstacleOnAxis != null) {
                            //存在障碍物
                            if (distance > 0) {
                                if (curObstacleOnAxis[1] != null) {
                                    int obstacleX = curObstacleOnAxis[1][0];
                                    int obstacleY = curObstacleOnAxis[1][1];
                                    if (startY == obstacleY) {
                                        //增加Y的检测, 是因为可能出现只有一个方向的障碍物时, 另一个方向, 会有默认值0,0
                                        //new int[][]创建障碍物时, 默认值为{0, 0}
                                        if (startX + distance >= obstacleX && obstacleX > startX) {
                                            distance = obstacleX - startX - 1;
                                        }
                                    }
                                }
                            } else {
                                if (curObstacleOnAxis[0] != null) {
                                    int obstacleX = curObstacleOnAxis[0][0];
                                    int obstacleY = curObstacleOnAxis[0][1];
                                    if (startY == obstacleY) {
                                        if (startX + distance <= obstacleX && obstacleX < startX) {
                                            distance = -(startX - obstacleX - 1);
                                        }
                                    }
                                }
                            }
                        }
                        startX = startX + distance;
                        if (startX < -3 * 10000) {
                            startX = -3 * 10000;
                        }
                    } else {
                        //Y轴上移动
                        if (curObstacleOnAxis != null) {
                            //存在障碍物
                            if (distance > 0) {
                                if (curObstacleOnAxis[1] != null) {
                                    int obstacleX = curObstacleOnAxis[1][0];
                                    int obstacleY = curObstacleOnAxis[1][1];
                                    if (startX == obstacleX) {
                                        if (startY + distance >= obstacleY && obstacleY > startY) {
                                            distance = obstacleY - startY - 1;
                                        }
                                    }
                                }
                            } else {
                                if (curObstacleOnAxis[0] != null) {
                                    int obstacleX = curObstacleOnAxis[0][0];
                                    int obstacleY = curObstacleOnAxis[0][1];
                                    if (startX == obstacleX) {
                                        if (startY + distance <= obstacleY && obstacleY < startY) {
                                            distance = -(startY - obstacleY - 1);
                                        }
                                    }
                                }
                            }
                        }
                        startY = startY + distance;
                        if (startY > 3 * 10000) {
                            startY = 3 * 10000;
                        }
                    }
//                    System.out.println("move to (" + startX + ", " + startY + ")");
                    moveDistance = startX * startX + startY * startY;
                    moveDistanceMax = Math.max(moveDistance, moveDistanceMax);
                }
            } else {
                System.err.println("commands[i] is one of the values in the list [-2,-1,1,2,3,4,5,6,7,8,9]");
            }
        }
        return Math.min(moveDistanceMax, DISTANCE_MAX - 1);
    }

    /**
     * 检测命令是否有效
     *
     * @param command 命令
     * @return
     */
    private static boolean checkCommandValid(int command) {
        int length = COMMANDS.length;
        for (int i = 0; i < length; i++) {
            if (COMMANDS[i] == command) {
                //直接退出遍历, 减少遍历次数
                return true;
            }
        }
        return false;
    }

    /**
     * 获取下一个方向
     *
     * @param curDirection 当前方向
     * @param command      命令
     * @return
     */
    private static int getNextDirection(int curDirection, int command) {
        //方向依次: 0, 1, 2, 3
        if (RIGHT == command) {
            //向右转, 顺时针+1
            return (curDirection + 1) % 4;
        }
        //向左转, 顺时针+3
        return (curDirection + 3) % 4;
    }

    /**
     * 使用二分法查找
     * @param startX
     * @param startY
     * @param obstaclesByOrderY
     * @return
     */
    private static int[][] findObstaclesOnXAxis(int startX, int startY, int[][] obstaclesByOrderY) {
        int oLength = obstaclesByOrderY == null ? 0 : obstaclesByOrderY.length;
        if (oLength == 0) {
            return null;
        }
        int startIndex = 0;
        int endIndex = oLength - 1;
        int middleIndex;
        while (startIndex <= endIndex) {
            middleIndex = (endIndex - startIndex) / 2 + startIndex;
            int[] point = obstaclesByOrderY[middleIndex];
            if (point[1] > startY) {
                //目标位于middleIndex之前
                endIndex = middleIndex - 1;
            } else if (point[1] < startY) {
                //目标位于middleIndex之后
                startIndex = middleIndex + 1;
            } else {
                //找到目标
                if (point[0] < startX) {
                    //y相同, 当前坐标x在起点x之前, 正序查找离startX最近的坐标
                    return findObstaclesByAsc(startX, startY, true,
                            obstaclesByOrderY, middleIndex, endIndex);
                } else if (point[0] > startX) {
                    //找y相同, 当前坐标x在终点x之后, 倒序查找离startX最近的坐标
                    return findObstaclesByDesc(startX, startY, true,
                            obstaclesByOrderY, startIndex, middleIndex);
                } else {
                    //障碍物节点等于当前节点, 这种情况不允许存在
                    System.out.println("error obstacle: " + point[0] + ", " + point[1]);
                    break;
                }
            }
        }
        return null;
    }


    /**
     * 使用二分法查找
     * @param startX
     * @param startY
     * @param obstaclesByOrderX
     * @return
     */
    private static int[][] findObstaclesOnYAxis(int startX, int startY, int[][] obstaclesByOrderX) {
        int oLength = obstaclesByOrderX == null ? 0 : obstaclesByOrderX.length;
        if (oLength == 0) {
            return null;
        }
        int startIndex = 0;
        int endIndex = oLength - 1;
        int middleIndex;
        while (startIndex <= endIndex) {
            middleIndex = (endIndex - startIndex) / 2 + startIndex;
            int[] point = obstaclesByOrderX[middleIndex];
            if (point[0] > startX) {
                //目标位于middleIndex之前
                endIndex = middleIndex - 1;
            } else if (point[0] < startX) {
                //目标位于middleIndex之后
                startIndex = middleIndex + 1;
            } else {
                //找到目标
                if (point[1] < startY) {
                    //y相同, 当前坐标x在起点x之前, 正序查找离startX最近的坐标
                    return findObstaclesByAsc(startX, startY, false,
                            obstaclesByOrderX, middleIndex, endIndex);
                } else if (point[1] > startY) {
                    //找y相同, 当前坐标x在终点x之后, 倒序查找离startX最近的坐标
                    return findObstaclesByDesc(startX, startY, false,
                            obstaclesByOrderX, startIndex, middleIndex);
                } else {
                    //障碍物节点等于当前节点, 这种情况不允许存在
                    System.out.println("error obstacle: " + point[0] + ", " + point[1]);
                    break;
                }
            }
        }
        return null;
    }

    /**
     * 倒序寻找移动距离
     * 进入这个方法的前提有两种：
     * 最后一个坐标y=startY, 第一个坐标x>startX
     * 最后一个坐标x=startX, 第一个坐标y>startY
     * @param startX
     * @param startY
     * @param moveOnXAxis
     * @param obstaclesByOrderXOrY
     * @param startIndex
     * @param endIndex
     * @return 第一个坐标是反向的障碍物, 第二个坐标是正向的障碍物
     */
    private static int[][] findObstaclesByDesc(int startX, int startY, boolean moveOnXAxis,
                                           int[][] obstaclesByOrderXOrY,
                                           int startIndex, int endIndex) {
        //此处只初始化坐标数量, 不初始化坐标, 即new int[2][]第二个中括号里面不设值
        int[][] obstacles = new int[2][];
        for (int i = endIndex; i >= startIndex; i--) {
            int[] point = obstaclesByOrderXOrY[i];
            if (moveOnXAxis) {
                //在x轴移动
                if (point[1] == startY) {
//                    System.out.println("obstacles: " + point[0] + ", " + point[1]);
                    if (point[0] < startX) {
                        //出现第一个小于startX的坐标就是反向最近的障碍物
                        obstacles[0] = point;
                        break;
                    } else {
                        //出现一个大于startX, 越来越接近startX, 最后一次就是最接近的障碍物
                        obstacles[1] = point;
                    }
                } else {
                    //出现第一个y不相等的点, 后面不会有满足条件的障碍物, 减少不必要的遍历
                    break;
                }
            } else {
                //在y轴移动
                if (point[0] == startX) {
                    //找到最接近起点x的x
//                    System.out.println("obstacles: " + point[0] + ", " + point[1]);
                    if (point[1] < startY) {
                        //出现第一个小于startY的坐标就是反向最近的障碍物
                        obstacles[0] = point;
                        break;
                    } else {
                        //出现一个大于startY, 越来越接近startY, 最后一次就是最接近的障碍物
                        obstacles[1] = point;
                    }
                } else {
                    //出现第一个y不相等的点, 后面不会有满足条件的障碍物, 减少不必要的遍历
                    break;
                }
            }
        }
        return obstacles;
    }

    /**
     * 正序寻找最近起点的障碍物
     * 进入这个方法的前提有两种：
     * 第一个坐标y=startY, 第一个坐标x<startX
     * 第一个坐标x=startX, 第一个坐标y<startY
     * @param startX
     * @param startY
     * @param moveOnXAxis
     * @param obstaclesByOrderXOrY
     * @param startIndex
     * @param endIndex
     * @return 第一个坐标是反向的障碍物, 第二个坐标是正向的障碍物
     */
    private static int[][] findObstaclesByAsc(int startX, int startY,
                                              boolean moveOnXAxis,
                                              int[][] obstaclesByOrderXOrY,
                                              int startIndex, int endIndex) {
        //此处只初始化坐标数量, 不初始化坐标, 即new int[2][]第二个中括号里面不设值
        int[][] obstacles = new int[2][];
        for (int i = startIndex; i <= endIndex; i++) {
            int[] point = obstaclesByOrderXOrY[i];
            if (moveOnXAxis) {
                //在X轴移动
                if (point[1] == startY) {
//                    System.out.println("obstacles: " + point[0] + ", " + point[1]);
                    if (point[0] > startX) {
                        //出现的第一个大于startX的坐标就是startX之后最近的障碍物
                        obstacles[1] = point;
                        break;
                    } else {
                        //因为数据是经过排序,只要出现小于startX,必然是越来越接近startX
                        obstacles[0] = point;
                    }
                } else {
                    //出现第一个y不相等的点, 后面不会有满足条件的障碍物, 减少不必要的遍历
                    break;
                }
            } else {
                //在Y轴移动
                if (point[0] == startX) {
                    //向后找, 第一个满足条件的就是会阻碍正常走动的点
//                    System.out.println("obstacles: " + point[0] + ", " + point[1]);
                    if (point[1] > startY) {
                        //出现的第一个大于startY的坐标就是startY之后最近的障碍物
                        obstacles[1] = point;
                        break;
                    } else {
                        //因为数据是经过排序,只要出现小于startY,必然是越来越接近startY
                        obstacles[0] = point;
                    }
                } else {
                    //出现第一个x不相等的点, 后面不会有满足条件的障碍物, 减少不必要的遍历
                    break;
                }
            }
        }
        return obstacles;
    }

    public static void main(String[] args) {
        int distance = 0;

        int[] commands = new int[]{1, 2, -2, 5, -1, -2, -1, 8, 3, -1, 9, 4, -2, 3, 2, 4, 3, 9, 2, -1, -1, -2, 1, 3, -2, 4, 1, 4, -1, 1, 9, -1, -2, 5, -1, 5, 5, -2, 6, 6, 7, 7, 2, 8, 9, -1, 7, 4, 6, 9, 9, 9, -1, 5, 1, 3, 3, -1, 5, 9, 7, 4, 8, -1, -2, 1, 3, 2, 9, 3, -1, -2, 8, 8, 7, 5, -2, 6, 8, 4, 6, 2, 7, 2, -1, 7, -2, 3, 3, 2, -2, 6, 9, 8, 1, -2, -1, 1, 4, 7};
        int[][] obstacles = new int[][]{{-57, -58}, {-72, 91}, {-55, 35}, {-20, 29}, {51, 70}, {-61, 88}, {-62, 99}, {52, 17}, {-75, -32}, {91, -22}, {54, 33}, {-45, -59}, {47, -48}, {53, -98}, {-91, 83}, {81, 12}, {-34, -90}, {-79, -82}, {-15, -86}, {-24, 66}, {-35, 35}, {3, 31}, {87, 93}, {2, -19}, {87, -93}, {24, -10}, {84, -53}, {86, 87}, {-88, -18}, {-51, 89}, {96, 66}, {-77, -94}, {-39, -1}, {89, 51}, {-23, -72}, {27, 24}, {53, -80}, {52, -33}, {32, 4}, {78, -55}, {-25, 18}, {-23, 47}, {79, -5}, {-23, -22}, {14, -25}, {-11, 69}, {63, 36}, {35, -99}, {-24, 82}, {-29, -98}, {-50, -70}, {72, 95}, {80, 80}, {-68, -40}, {65, 70}, {-92, 78}, {-45, -63}, {1, 34}, {81, 50}, {14, 91}, {-77, -54}, {13, -88}, {24, 37}, {-12, 59}, {-48, -62}, {57, -22}, {-8, 85}, {48, 71}, {12, 1}, {-20, 36}, {-32, -14}, {39, 46}, {-41, 75}, {13, -23}, {98, 10}, {-88, 64}, {50, 37}, {-95, -32}, {46, -91}, {10, 79}, {-11, 43}, {-94, 98}, {79, 42}, {51, 71}, {4, -30}, {2, 74}, {4, 10}, {61, 98}, {57, 98}, {46, 43}, {-16, 72}, {53, -69}, {54, -96}, {22, 0}, {-7, 92}, {-69, 80}, {68, -73}, {-24, -92}, {-21, 82}, {32, -1}, {-6, 16}, {15, -29}, {70, -66}, {-85, 80}, {50, -3}, {6, 13}, {-30, -98}, {-30, 59}, {-67, 40}, {17, 72}, {79, 82}, {89, -100}, {2, 79}, {-95, -46}, {17, 68}, {-46, 81}, {-5, -57}, {7, 58}, {-42, 68}, {19, -95}, {-17, -76}, {81, -86}, {79, 78}, {-82, -67}, {6, 0}, {35, -16}, {98, 83}, {-81, 100}, {-11, 46}, {-21, -38}, {-30, -41}, {86, 18}, {-68, 6}, {80, 75}, {-96, -44}, {-19, 66}, {21, 84}, {-56, -64}, {39, -15}, {0, 45}, {-81, -54}, {-66, -93}, {-4, 2}, {-42, -67}, {-15, -33}, {1, -32}, {-74, -24}, {7, 18}, {-62, 84}, {19, 61}, {39, 79}, {60, -98}, {-76, 45}, {58, -98}, {33, 26}, {-74, -95}, {22, 30}, {-68, -62}, {-59, 4}, {-62, 35}, {-78, 80}, {-82, 54}, {-42, 81}, {56, -15}, {32, -19}, {34, 93}, {57, -100}, {-1, -87}, {68, -26}, {18, 86}, {-55, -19}, {-68, -99}, {-9, 47}, {24, 94}, {92, 97}, {5, 67}, {97, -71}, {63, -57}, {-52, -14}, {-86, -78}, {-17, 92}, {-61, -83}, {-84, -10}, {20, 13}, {-68, -47}, {7, 28}, {66, 89}, {-41, -17}, {-14, -46}, {-72, -91}, {4, 52}, {-17, -59}, {-85, -46}, {-94, -23}, {-48, -3}, {-64, -37}, {2, 26}, {76, 88}, {-8, -46}, {-19, -68}};
        distance = SimulateRobotWalk.robotSim(commands, obstacles);
        System.out.println("move distance max: " + distance);

        commands = new int[]{-2, -1, -2, 3, 7};
        obstacles = new int[][]{{1, -3}, {2, -3}, {4, 0}, {-2, 5}, {-5, 2}, {0, 0}, {4, -4}, {-2, -5}, {-1, -2}, {0, 2}};
//        distance = SimulateRobotWalk.robotSim(commands, obstacles);
//        System.out.println("move distance max: " + distance);

        commands = new int[]{6, 6, 4, 7, 8, 4, 4, 9, 3, 4, -2, -1, 1, 1, -1, 6, 9, -2, 9, 4, 8, 6, 9, -1, 2, 5, 1, 5, -2, 6, 3, 5, -2, -1, 7, 7, -1, 6, 6, 9, -1, 1, 3, -2, 4, -1, 7, 4, 1, 6, -2, 2, -2, 3, 8, 3, -1, 3, 5, -2, -1, 1, 4, -1, 8, 2, -2, 1, 2, 3, 8, 1, 3, 8, 1, -1, 2, 3, 3, 8, 7, 3, 7, 7, 1, 9, 2, 5, -1, 1, -1, 4, 1, 6, 1, -1, 5, 9, 4, 4};
        obstacles = new int[][]{{51, -36}, {55, -35}, {-34, -7}, {23, -11}, {-94, 81}, {0, 26}, {-33, 52}, {59, -55}, {4, 53}, {100, 96}, {11, -71}, {22, 49}, {25, -57}, {-34, 4}, {54, -95}, {-87, 14}, {45, -44}, {21, -16}, {23, 75}, {-82, 86}, {54, 68}, {47, -90}, {-64, -4}, {82, -6}, {-27, 90}, {-27, -22}, {-48, -92}, {-67, 30}, {22, -58}, {-36, 15}, {-22, 23}, {-57, -66}, {74, 77}, {14, 44}, {-30, -82}, {-67, -33}, {90, -23}, {-10, 74}, {-54, 25}, {63, 63}, {82, 11}, {-90, 73}, {-51, 37}, {-76, -17}, {-39, -68}, {97, 25}, {91, 29}, {-44, -56}, {-34, 22}, {95, 7}, {68, -83}, {89, 50}, {86, 72}, {-42, 59}, {40, -17}, {61, -41}, {98, -24}, {71, -49}, {86, -55}, {79, 77}, {-44, -79}, {-25, -47}, {92, 66}, {-6, 9}, {37, -48}, {0, 84}, {-60, -86}, {-99, 29}, {38, -34}, {-15, 8}, {-26, -96}, {70, 86}, {-62, 35}, {43, 55}, {78, -28}, {87, 90}, {-90, -72}, {72, 73}, {6, -94}, {-12, 54}, {-88, 62}, {80, 51}, {-73, -47}, {58, 16}, {36, 56}, {9, -29}, {38, -68}, {7, -30}, {77, 5}, {52, -19}, {89, -6}, {69, -15}, {-98, 64}, {84, 24}, {94, -82}, {-65, -14}, {-43, 6}, {-7, 87}, {60, 17}, {-55, -68}, {11, -6}, {54, 78}, {16, 8}, {92, -25}, {-75, -70}, {-35, -94}, {-67, 93}, {-2, -9}, {28, 51}, {-68, 15}, {76, 96}, {-85, -15}, {0, 74}, {-65, -53}, {-84, -16}, {-100, 16}, {-12, 70}, {-30, 18}, {14, 49}, {28, -73}, {47, 48}, {15, -42}, {47, 41}, {49, 79}, {27, 44}, {-45, -19}, {-2, 21}, {-39, -96}, {44, 43}, {-61, 30}, {4, -66}, {-83, 35}, {100, 14}, {74, 73}, {45, 9}, {53, -76}, {40, -85}, {-24, -29}, {-49, -39}, {-22, -98}, {-96, -71}, {15, -79}, {34, 45}, {87, -33}, {-13, 79}, {-88, -11}, {53, 70}, {71, 81}, {-42, -25}, {-84, -47}, {27, 35}, {-66, -76}, {2, -98}, {-61, 72}, {95, -74}, {75, -72}, {-32, 90}, {-51, -20}, {-23, -77}, {-34, -26}, {5, 81}, {-7, 33}, {69, -4}, {-12, 27}, {-83, 2}, {1, 86}, {69, -1}, {38, -29}, {32, 59}, {-49, -90}, {33, -43}, {-90, 92}, {98, 98}, {68, 0}, {1, -41}, {44, 70}, {44, 26}, {58, -90}, {30, -15}, {-88, 88}, {-33, 34}, {-67, 41}, {-28, -62}, {76, -70}, {-92, 82}, {8, 70}, {-6, 67}, {66, -18}, {92, -82}, {-37, 94}, {8, -82}, {-52, 71}, {-86, 42}, {-30, 4}, {92, -73}, {97, 3}, {73, 75}, {81, -44}, {-93, 95}, {0, -90}};
//        distance = SimulateRobotWalk.robotSim(commands, obstacles);
//        System.out.println("move distance max: " + distance);
    }

}
